<?php
// Call TimeControllerTest::main() if this source file is executed directly.
if (!defined("PHPUnit_MAIN_METHOD")) {
    define("PHPUnit_MAIN_METHOD", "TimeControllerTest::main");
}

require_once "PHPUnit/Framework/TestCase.php";
require_once "PHPUnit/Framework/TestSuite.php";

require_once "testConf.php";
require_once 'TimeController.php';

require_once ROOT_PATH . "/lib/confs/Conf.php";
require_once ROOT_PATH . '/lib/models/time/Timesheet.php';
require_once ROOT_PATH . '/lib/models/time/TimeEvent.php';

require_once ROOT_PATH . '/lib/models/eimadmin/Customer.php';
require_once ROOT_PATH . '/lib/models/eimadmin/Projects.php';

require_once ROOT_PATH . '/lib/common/TemplateMerger.php';
require_once ROOT_PATH . '/lib/common/authorize.php';

require_once ROOT_PATH . '/lib/models/hrfunct/EmpInfo.php';
require_once ROOT_PATH . '/lib/models/hrfunct/EmpRepTo.php';

/**
 * Test class for TimeController.
 * Generated by PHPUnit_Util_Skeleton on 2007-08-13 at 07:24:39.
 */
class TimeControllerTest extends PHPUnit_Framework_TestCase {
    /**
     * Runs the test methods of this class.
     *
     * @access public
     * @static
     */
    public static function main() {
        require_once "PHPUnit/TextUI/TestRunner.php";

        $suite  = new PHPUnit_Framework_TestSuite("TimeControllerTest");
        $result = PHPUnit_TextUI_TestRunner::run($suite);
    }

    /**
     * Sets up the fixture, for example, open a network connection.
     * This method is called before a test is executed.
     *
     * @access protected
     */
    protected function setUp() {
    	$_SESSION['empID'] = "010";
    	$_SESSION['isAdmin'] = false;

    	$conf = new Conf();

    	$this->connection = mysql_connect($conf->dbhost.":".$conf->dbport, $conf->dbuser, $conf->dbpass);
		mysql_select_db($conf->dbname);
		$this->_cleanup();
        mysql_query("INSERT INTO hs_hr_employee(emp_number, employee_id, emp_lastname, emp_firstname, emp_middle_name) " .
                                "VALUES(10, '010', 'Rajasinghe', 'Saman', 'Marlon')");
    	mysql_query("INSERT INTO `hs_hr_timesheet_submission_period` (`timesheet_period_id`, `name`, `frequency`, `period`, `start_day`, `end_day`, `description`) ".
    				"VALUES (10, 'Permanent', 7, 1, ".@date('N').", ".@date('N', time()*3600*24*7).", 'Testing')");
    	mysql_query("INSERT INTO `hs_hr_timesheet` (`timesheet_id`, `employee_id`, `timesheet_period_id`, `start_date`, `end_date`, `status`) ".
    				"VALUES (10, 10, 10, '2007-05-14', '2007-05-20', 0)");
    }

    /**
     * Tears down the fixture, for example, close a network connection.
     * This method is called after a test is executed.
     *
     * @access protected
     */
    protected function tearDown() {
    	$this->_cleanup();
    }

    /**
     * Tests validateTimeEvents method.
     */
    public function testValidateTimeEvents() {
		$timeController = new TimeController();
		$timeEvents[] = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 00:01', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc 1");
		$timeEvents[] = $this->_getTimeEvent(2, 10, 10, 10, '2007-05-17 12:00', '2007-05-18 15:00', '2007-07-07',
											27*3600, "desc 2");
		$timeEvents[] = $this->_getTimeEvent(3, 10, 10, 10, '2007-05-20 22:00', '2007-05-20 23:59', '2007-07-07',
											2*3600 - 60, "desc 2");

		$retVal = $timeController->validateTimeEvents($timeEvents);
		$this->assertTrue( $retVal === true, "Got $retVal instead of true");

		// Invalid timesheet Id
		$timeEvents[1]->setTimesheetId(12);
		$this->assertTrue($timeController->validateTimeEvents($timeEvents) === TimeController::NO_TIMESHEET_FAILURE);

		// Empty timesheet id
		$timeEvents[1]->setTimesheetId(null);
		$this->assertTrue($timeController->validateTimeEvents($timeEvents) === TimeController::NO_TIMESHEET_FAILURE);

		// Time event outside timesheet period
		$timeEvents[1]->setTimesheetId(10);
		$timeEvents[1]->setStartTime('2007-05-13 23:33');
		$this->assertTrue($timeController->validateTimeEvents($timeEvents) === TimeController::EVENT_OUTSIDE_PERIOD_FAILURE);

		// Check that duration and end time is set for the time events by validateTimeEvents
		$timeEvents = array();
		$timeEvents[] = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 00:01', '2007-05-14 15:00', '2007-07-07', "", "desc 1");
		$timeEvents[] = $this->_getTimeEvent(2, 10, 10, 10, '2007-05-17 12:00', '2007-05-18 15:00', '2007-07-07', "", "desc 2");
		$timeEvents[] = $this->_getTimeEvent(3, 10, 10, 10, '2007-05-20 22:00', '', '2007-07-07', 3600, "desc 2");
		$this->assertSame(true, $timeController->validateTimeEvents($timeEvents));

		$this->assertSame(15*3600 - 60, $timeEvents[0]->getDuration());
		$this->assertSame(27*3600, $timeEvents[1]->getDuration());
		$this->assertSame("2007-05-20 23:00", $timeEvents[2]->getEndTime());

    }

    /**
     * Tests validateTimeEvent method.
     */
    public function testValidateTimeEvent() {

		$timeController = new TimeController();

		$timesheet1 = $this->_getTimesheet(11, 10, 10, '2007-05-14', '2007-05-20', 0);

		// Test time event within timesheet period
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(true, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// Test time event out side timesheet period
		$timeEvent = $this->_getTimeEvent(2, 10, 10, 10, '2007-05-13 12:00', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		$timeEvent = $this->_getTimeEvent(3, 10, 10, 10, '2007-05-21 00:10', '2007-05-21 03:10', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		$timeEvent = $this->_getTimeEvent(4, 10, 10, 10, '2007-05-13 23:30', '2007-05-14 04:30', '2007-07-07',
											5*3600, "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		$timeEvent = $this->_getTimeEvent(5, 10, 10, 10, '2007-05-20 23:30', '2007-05-21 04:30', '2007-07-07',
											5*3600, "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		$timeEvent = $this->_getTimeEvent(5, 10, 10, 10, '2007-05-21 07:30', '2007-05-21 04:30', '2007-07-07',
											5*3600, "desc");
		$this->assertSame(TimeController::ZeroOrNegativeIntervalSpecified_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));


		// Test invalid timesheet periods
		$timesheet2 = $this->_getTimesheet(11, 10, 10, '2007-05-14', '', 0);
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::INVALID_TIMESHEET_PERIOD_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet2));

		$timesheet2 = $this->_getTimesheet(11, 10, 10, '', '2007-05-14', 0);
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::INVALID_TIMESHEET_PERIOD_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet2));

		$timesheet2 = $this->_getTimesheet(11, 10, 10, '2007-05-15', '2007-05-14', 0);
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::INVALID_TIMESHEET_PERIOD_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet2));

		// Empty project Id
		$timeEvent = $this->_getTimeEvent(1, null, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::ProjectNotSpecified_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// Empty activity Id
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc", "");
		$this->assertSame(TimeController::ActivityNotSpecified_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// invalid start time
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-15-13 12:00', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::InvalidStartTime_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// Invalid end time
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', 'xyz', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::InvalidEndTime_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// reported date not given
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '',
											3*3600, "desc");
		$this->assertSame(TimeController::ReportedDateNotSpecified_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// invalid reported date
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '929-19-191',
											3*3600, "desc");
		$this->assertSame(TimeController::InvalidReportedDate_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// Empty duration allowed
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											"", "desc");
		$this->assertSame(true, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// 0 duration allowed for event with id
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											"0", "desc");
		$this->assertSame(true, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// Invalid duration values
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											"-1", "desc");
		$this->assertSame(TimeController::InvalidDuration_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// 0 duration not allowed for new entry (without event id)
		$timeEvent = $this->_getTimeEvent("", 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											"0", "desc");
		$this->assertSame(TimeController::InvalidDuration_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// Reported date and duration given
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '', '', '2007-05-14', 3*3600, "desc");
		$this->assertSame(true, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// Reported date outside period
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '', '', '2007-05-13', 3*3600, "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '', '', '2007-05-21', 3*3600, "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '', '', '2007-05-20', 25*3600, "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// zero duration + reported date
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '', '', '2007-05-20', 0, "desc");
		$this->assertSame(TimeController::NoValidDurationOrInterval_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// Reported date on period end date
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '', '', '2007-05-20', 10*3600, "desc");
		$this->assertSame(true, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// Only start time given
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '', '2007-05-20', "", "desc");
		$this->assertSame(true, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// start time outside timesheet period
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-13 23:00', '', '2007-05-20', "", "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-21 12:00', '', '2007-05-20', "", "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// start time and end time given
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 13:00', '2007-05-20', "", "desc");
		$this->assertSame("", $timeEvent->getDuration());
		$this->assertSame(true, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// check duration is set
		$this->assertSame(3600, $timeEvent->getDuration());

		// start time == end time
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 13:10', '2007-05-14 13:10', '2007-05-20', "", "desc");
		$this->assertSame(TimeController::ZeroOrNegativeIntervalSpecified_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// start time == end time and duration == 0
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 13:10', '2007-05-14 13:10', '2007-05-20', "", "desc");
		$this->assertSame(TimeController::ZeroOrNegativeIntervalSpecified_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// start time > end time
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 13:11', '2007-05-14 13:10', '2007-05-20', "", "desc");
		$this->assertSame(TimeController::ZeroOrNegativeIntervalSpecified_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// start time outside timesheet period
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-13 13:11', '2007-05-13 13:30', '2007-05-20', "", "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// end time outside timesheet period
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-13 21:11', '2007-05-21 13:30', '2007-05-20', "", "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// start time and duration given
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(true, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// end time set
		$this->assertSame("2007-05-14 15:00", $timeEvent->getEndTime());

		// start outside period
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-13 12:00', '', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// End time outside period
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-12 22:00', '', '2007-07-07',
											5*3600, "desc");
		$this->assertSame(TimeController::EVENT_OUTSIDE_PERIOD_FAILURE, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// Start time and zero duration not allowed
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 22:00', '', '2007-07-07', 0, "desc");
		$this->assertSame(TimeController::NoValidDurationOrInterval_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// start, end and duration allowed for events with id
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(true, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// start, end and duration not allowed for new events
		$timeEvent = $this->_getTimeEvent("", 10, 10, 10, '2007-05-14 12:00', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::NotAllowedToSpecifyDurationAndInterval_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// End time and duration not allowed
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '', '2007-05-14 15:00', '2007-07-07',
											3*3600, "desc");
		$this->assertSame(TimeController::NoValidDurationOrInterval_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// End time only not allowed
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '', '2007-05-14 15:00', '2007-07-07', "", "desc");
		$this->assertSame(TimeController::NoValidDurationOrInterval_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, null, '2007-05-14 15:00', '2007-07-07', null, "desc");
		$this->assertSame(TimeController::NoValidDurationOrInterval_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		// just reported date not allowed
		$timeEvent = $this->_getTimeEvent(1, 10, 10, 10, '', '', '2007-07-07', "", "desc");
		$this->assertSame(TimeController::NoValidDurationOrInterval_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		$timeEvent = $this->_getTimeEvent("", 10, 10, 10, '', '', '2007-07-07', "", "desc");
		$this->assertSame(TimeController::NoValidDurationOrInterval_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

		$timeEvent = $this->_getTimeEvent("", 10, 10, 10, null, null, '2007-07-07', null, "desc");
		$this->assertSame(TimeController::NoValidDurationOrInterval_ERROR, $timeController->validateTimeEvent($timeEvent, $timesheet1));

    }

	/**
	 * Constructs and returns time event with given parameters
	 */
	private function _getTimeEvent($timeEventId, $projectId, $employeeId, $timesheetId, $startTime,
			$endTime, $reportedDate, $duration, $description, $activityId = 1) {

		$timeEvent = new TimeEvent();
		$timeEvent->setTimeEventId($timeEventId);
		$timeEvent->setActivityId($activityId);
		$timeEvent->setProjectId($projectId);
		$timeEvent->setEmployeeId($employeeId);
		$timeEvent->setTimesheetId($timesheetId);
		$timeEvent->setStartTime($startTime);
		$timeEvent->setEndTime($endTime);
		$timeEvent->setReportedDate($reportedDate);
		$timeEvent->setDuration($duration);
		$timeEvent->setDescription($description);

		return $timeEvent;
	}

	/**
	 * Create and return a timesheet object with given parameters.
	 */
	private function _getTimesheet($timesheetId, $employeeId, $timesheetPeriodId, $startDate, $endDate, $status) {

		$timesheet = new Timesheet();
		$timesheet->setTimesheetId($timesheetId);
		$timesheet->setTimesheetId($timesheetPeriodId);
		$timesheet->setEmployeeId($employeeId);
		$timesheet->setStartDate($startDate);
		$timesheet->setEndDate($endDate);
		$timesheet->setStatus($status);

		return $timesheet;
	}

	/**
	 * Clean up database entries created during test.
	 */
	private function _cleanup() {
    	$this->assertTrue(mysql_query("TRUNCATE TABLE `hs_hr_timesheet`"), mysql_error());
    	$this->assertTrue(mysql_query("DELETE FROM `hs_hr_timesheet_submission_period` WHERE `timesheet_period_id` = 10"));
    	$this->assertTrue(mysql_query("DELETE FROM `hs_hr_employee` WHERE `emp_number` = 10"));
	}
}

// Call TimeControllerTest::main() if this source file is executed directly.
if (PHPUnit_MAIN_METHOD == "TimeControllerTest::main") {
    TimeControllerTest::main();
}
?>
